﻿//Copyright © 2012  Daniel Lopez

//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Security.Cryptography;
using Microsoft.WindowsAPICodePack.Shell;
namespace NASM_Develop_IDE
{
    public partial class CustomScriptDialog : GlassForm
    {
        private Solution solution;
        private string output;
        public CustomScriptDialog(Solution solution)
        {
            if (solution == null) throw new ArgumentNullException("Solution must not be null!");
            InitializeComponent();
            this.scriptEditor = new ScintillaNET.Scintilla();
            this.scriptEditor.Location = new Point(9, 58);
            this.scriptEditor.Size = new System.Drawing.Size(625, 395);
            this.panel.Controls.Add(this.scriptEditor);
            this.solution = solution;
            TextBoxHighlighter.Highlight(binaryOutputName, "Enter Binary Output Name (This Field Is Optional In Case Project Cannot Find Output Name)");
            AeroGlassCompositionChanged += new EventHandler<AeroGlassCompositionChangedEventArgs>(CustomScriptDlg_AeroGlassCompositionChanged);
            if (AeroGlassCompositionEnabled)
            {
                ExcludeControlFromAeroGlass(panel);
            }
            else
            {
                BackColor = Color.Aqua;
            }
        }
        void CustomScriptDlg_AeroGlassCompositionChanged(object sender, AeroGlassCompositionChangedEventArgs e)
        {
            if (e.GlassAvailable)
            {

                ExcludeControlFromAeroGlass(panel);
                Invalidate();
            }
            else
            {

                this.BackColor = Color.Aqua;
            }
        }
        private void scriptType_SelectionChangeCommitted(object sender, EventArgs e)
        {
          
            int selectedIndex = scriptType.SelectedIndex;

            if (selectedIndex == 0)
            {
                    scriptEditor.Margins[0].Width = 20;
                    scriptEditor.Margins[1].Width = 32;
                    scriptEditor.Margins[1].IsMarkerMargin = true;
                    scriptEditor.Margins[1].Type = ScintillaNET.MarginType.Symbol;
                    scriptEditor.Markers[1].Symbol = ScintillaNET.MarkerSymbol.Arrows;
                    scriptEditor.Markers[1].ForeColor = Color.Red;      
                    scriptEditor.ConfigurationManager.CustomLocation = "Powershell.xml";
                    scriptEditor.ConfigurationManager.Language = "bash";
                    scriptEditor.ConfigurationManager.Configure();
                    scriptEditor.Text = "#Copyright © 2012  Daniel Lopez\r\n#This program is free software; you can redistribute it and/or\r\n#modify it under the terms of the GNU General Public License\r\n#as published by the Free Software Foundation; either version 2\r\n#of the License, or (at your option) any later version.\r\n\r\n#This program is distributed in the hope that it will be useful,\r\n#but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n#GNU General Public License for more details.\r\n\r\n#You should have received a copy of the GNU General Public License\r\n#along with this program; if not, write to the Free Software\r\n#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r\n\r\n#Note: Script can be modified but do not modify function declaration or command line arguments.\r\n\r\n\r\nfunction Compile([string[]]$i, [string[]]$o)\r\n{\r\n    $count = $i.length\r\n    $count2 = $o.length\r\n    if ($count.Equals($count2))\r\n    {\r\n        for($index = 0; $index -lt $count; $index++)\r\n        {\r\n            (nasm -fwin32 -o $o[$index] $i[$index] )  2>&1  | foreach-object {$_.ToString()} | tee -variable err\r\n            echo $err\r\n        }\r\n        \r\n    }\r\n}\r\n\r\nfunction Link([string[]]$objs, [string]$o)\r\n{\r\n    $objects = \"\"\r\n    foreach($obj in $objs)\r\n    {\r\n        $objects += ($obj + \" \")\r\n    }\r\n    (gcc $objects -o $o) 2>&1  | foreach-object {$_.ToString()} | tee -variable err\r\n    echo $err\r\n}\r\n\r\nif ($args.Count.Equals(3))\r\n{\r\n    if ($args[0].Count.Equals($args[1].Count))\r\n    {\r\n        \r\n        Compile $args[0] $args[1]\r\n        Link $args[1] $args[2]\r\n    }\r\n    else\r\n    {\r\n        echo \"Argument 1 and Argument 2 Must Have The Same Array Size!\"\r\n    }\r\n}\r\nelse\r\n{\r\n    echo \"Invalid amount of arguments\"\r\n}\r\n";
                    scriptEditor.Styles[2].ForeColor = Color.Green;
            }
        }


        private void scriptEditor_TextChanged(object sender, EventArgs e)
        {
            
        }

        private void scriptEditor_KeyUp(object sender, KeyEventArgs e)
        {

        }
        public string BuildOutput
        {
            get
            {
                return output;
            }
        }
        private void build_Click(object sender, EventArgs e)
        {
            bool successfull = NASMBuilder.Clean(solution.AbsolutePathOfBinFolder);
            Console.WriteLine(successfull ? "" : "Failed To Build Before Cleaning");
            if (scriptType.SelectedIndex == 0)
            {
                string tempPath = Path.GetTempPath();
                string fileName = getRandomName();
                using (StreamWriter writer = new StreamWriter(tempPath + fileName))
                {
                    writer.Write(scriptEditor.Text);
                }
                List<string> pathOfObjects = new List<string>();
                solution.AbsolutePathOfSources.ForEach(delegate(string path)
                {
                    pathOfObjects.Add(solution.AbsolutePathOfBinFolder + "\\" + Path.GetFileNameWithoutExtension(path) + ".obj");
                });
                output = NASMBuilder.BuildFromScript(tempPath + fileName, solution.AbsolutePathOfSources.ToArray(), pathOfObjects.ToArray(), solution.AbsolutePathOfBinFolder + "\\" + binaryOutputName.Text);
                if (binaryOutputName.Text != "")
                {
                    solution.NameOfOutputBinary = (!binaryOutputName.Text.EndsWith(".exe")) ? (binaryOutputName.Text + ".exe") : (binaryOutputName.Text);
                }
                else
                {
                    solution.NameOfOutputBinary = "default.exe";
                }
                solution.UpdateSolution();
                try
                {
                    File.Delete(tempPath + fileName);
                }
                catch
                {
                    Console.Write("Failed To Delete Temp File!");
                }
                this.Close();

            }
            else
            {
                MessageBox.Show("Please select a valid script type!", "What the!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private string getRandomName()
        {
            RandomNumberGenerator gen = RandomNumberGenerator.Create();
            byte[] bytes = new byte[50];
            gen.GetNonZeroBytes(bytes);
            return new UnicodeEncoding().GetString(bytes) + ".ps1";
        }

        private void cancelButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}
